package top.goldenyear.porpoise.framework.web.core.generator.dialect.impl;

import top.goldenyear.porpoise.framework.web.core.generator.dialect.IDialect;
import top.goldenyear.porpoise.framework.web.core.generator.model.ColumnMeta;
import top.goldenyear.porpoise.framework.web.core.generator.model.TableMeta;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.*;

/**
 * Sqlite 方言实现
 *
 * @author airhead
 */
public class SqliteDialect implements IDialect {

  @Override
  public void buildTableColumns(TableMeta tableMeta, DatabaseMetaData dbMeta, Connection conn)
      throws SQLException {
    Statement statement = conn.createStatement();
    ResultSet rs = statement.executeQuery("pragma table_info(" + tableMeta.getName() + ")");

    // cid  name       type     notnull  dflt_value  pk
    // ---  ---------  -------  -------  ----------  --
    // 0    EventId    INTEGER  0                    1
    // 1    EventName           0                    0
    // 2    StartDate           0                    0
    // 3    EndDate             0                    0

    while (rs.next()) {
      ColumnMeta columnMeta = new ColumnMeta();
      columnMeta.setName(rs.getString(2));

      String type = rs.getString(3);
      columnMeta.setType(type);
      columnMeta.setPropertyType(type2ClassName(type));

      tableMeta.addColumn(columnMeta);
    }
  }

  @Override
  public ResultSet getTablesResultSet(
      DatabaseMetaData dbMeta, Connection conn, String schema, String[] types) throws SQLException {
    return dbMeta.getTables(conn.getCatalog(), schema, null, types);
  }

  private String type2ClassName(String type) {
    int indexOf = type.indexOf("(");
    if (indexOf > 0) {
      type = type.substring(0, indexOf);
    }
    type = type.toLowerCase();
    return switch (type) {
      case "integer", "int", "int2", "int8", "tinyint", "smallint", "mediumint" ->
          Integer.class.getName();
      case "bigint", "unsigned bigint" -> BigInteger.class.getName();
      case "double", "numeric", "real" -> Double.class.getName();
      case "float" -> Float.class.getName();
      case "decimal" -> BigDecimal.class.getName();
      case "character",
              "varchar",
              "nchar",
              "nvarchar",
              "varying character",
              "native character",
              "text",
              "clob" ->
          String.class.getName();
      default -> String.class.getName();
    };
  }
}
